<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  <script>
   /*  Function.prototype.call = function (obj, ...args) {
      console.log('call()')
      // this(...args)
      // 处理obj的特殊值
      if (obj===undefined || obj===null) {
        // obj = window
        return this(...args)
      }

      // 给obj添加一个指向当前函数的临时方法
      obj.tempFn = this
      // 通过obj调用这个方法
      const result = obj.tempFn(...args)
      // 删除添加的临时方法
      delete obj.tempFn
      // 返回函数执行的结果
      return result
    } */

    function myCall(fn, obj, ...args) {
      console.log('myCall()')
      // this(...args)
      // 处理obj的特殊值
      if (obj===undefined || obj===null) {
        // obj = window
        return fn(...args)
      }

      // 给obj添加一个指向当前函数的临时方法
      obj.tempFn = fn
      // 通过obj调用这个方法
      const result = obj.tempFn(...args)
      // 删除添加的临时方法
      delete obj.tempFn
      // 返回函数执行的结果
      return result
    }

    function myApply(fn, obj, args) {
      console.log('myApply()')
      return myCall(fn, obj, ...args)
    }


    function myBind(fn, obj, ...args) {
      // 返回新函数
      return (...args2) => {
        // 通过call来调用原函数, 指定this为obj, 参数指定为args和args2
        return myCall(fn, obj, ...args, ...args2)
      }
    }
  </script>
  
  <script>
   
   
    var m = 1

    function fn(a, b) {
      console.log(a, b, this.m, this)
      return a + b
    }

    const obj = {
      m: 2
    }

    // console.log(fn.call(obj, 3, 4))  // 3 4 2 obj
    // console.log(fn.call(null, 3, 4))  // 3 4 2 obj

    // console.log(myCall(fn, obj, 3, 4))
    // console.log(myApply(fn, obj, [3, 4]))

    // console.log(fn.bind(obj)(3, 4))
    // console.log(fn.bind(obj, 5)(3, 4))
    // console.log(fn.bind(obj, 5, 6)(3, 4))

    console.log(myBind(fn, obj)(3, 4))
    console.log(myBind(fn, obj, 5)(3, 4))
    console.log(myBind(fn, obj, 5, 6)(3, 4))




  </script>
</body>
</html>